home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- Module name: transformations utility package.
-
- Authors: W.T. Hewitt, K.M. Singleton.
-
- Function: contains functions for performing two-dimensional and
- three-dimensional transformations.
-
- Dependencies: machine.h, transformtypes.h.
-
- Internal function list: validbounds.
-
- External function list: ptk_equal, ptk_point, ptk_point3, ptk_vector,
- ptk_vector3, ptk_vec3topt3, ptk_pt3tovec3, ptk_limit, ptk_limit3,
- ptk_dotv, ptk_crossv,
- ptk_nullv, ptk_modv, ptk_unitv, ptk_scalev, ptk_subv, ptk_addv,
- ptk_unitmatrix3, ptk_transposematrix3, ptk_multiplymatrix3,
- ptk_concatenatematrix3,
- ptk_shift3, ptk_scale3, ptk_rotatecs3, ptk_rotate3, ptk_shear3,
- ptk_rotatevv3, ptk_rotateline3, ptk_pt3topt4, ptk_pt4topt3, ptk_transform4,
- ptk_transform3, ptk_matrixtomatrix3, ptk_outputmatrix3, ptk_box3tobox3,
- ptk_accumulatetran3, ptk_evalvieworientation3,
- ptk_evalviewmapping3, ptk_stackmatrix3, ptk_unstackmatrix3,
- ptk_examinestackmatrix3,
- ptk_3ptto3pt, ptk_0to3pt, ptk_oto3pt, ptk_invertmatrix3.
-
- Hashtables used: none.
-
- Modification history: (Version), (Date), (Name), (Description).
-
- 1.0, 2nd February 1986, W.T. Hewitt, First version.
-
- 1.1, 1st April 1986, K.M. Singleton, W.T. Hewitt, Added viewing
- and other utility routines.
-
- 1.2, 8th June 1987, K.M. Wyrwas, Added routine to invert a matrix.
-
- 1.3, 8th July 1988, S.Larkin, Modified to work with VAX PHIGS$.
-
- 1.4, 30th October 1990, W.T. Hewitt, Fixed to work with VAX PHIGS$.
-
- 2.0, 4th January 1991, G. Williams, Converted from Pascal to C.
-
- 2.1, 13th February 1991, G. Williams, Added functions - ptk_vector3,
- ptk_vec3topt3 and ptk_pt3tovec3.
-
- 2.2, 3rd May 1991, G. Williams, Added function - ptk_3x3to4x4.
-
- 3.0, June 1992, G. Williams, Converted to ISO PHIGS C.
-
- ----------------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <math.h>
- #ifdef SUN
- #include <malloc.h>
- #include <memory.h>
- #endif
- #include "machine.h"
- #include "ptktype.h"
- #include "trantype.h"
-
- /* Pointer records */
-
- typedef struct ptksstack3
- {
- Pmatrix3 ptkamat;
- struct ptksstack3 *ptkpnext;
- } ptksstack3;
-
- typedef struct ptksstack
- {
- Pmatrix ptkamat;
- struct ptksstack *ptkpnext;
- } ptksstack;
-
- #define ptkcdtor (3.14159263 / 180.0)
-
- static ptksstack3 *listhead3 = NULL, *newone3 = NULL;
- static ptksstack *listhead = NULL, *newone = NULL;
-
- /* global variable for ptkcpceps */
-
- Pfloat ptkveps = ptkcpceps;
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern ptkboolean ptk_equal(C(Pfloat) one, C(Pfloat) two)
- PreANSI(Pfloat one)
- PreANSI(Pfloat two)
- /*
- ** \parambegin
- ** \param{Pfloat}{one}{floating point number}{IN}
- ** \param{Pfloat}{two}{floating point number}{IN}
- ** \paramend
- ** \blurb{This function returns TRUE if \pardesc{one} and \pardesc{two}
- ** are equal, or their difference is less than the global
- ** constant tolerance \pardesc{ptkveps}. This is a global
- ** variable of type \pardesc{Pfloat} which may be changed by the application.
- ** The default value of \pardesc{ptkveps} is 1.0e-7.}
- */
- {
- Pfloat x, y;
-
- x = (Pfloat)one;
- y = (Pfloat)two;
- return (fabs(x - y) <= ptkveps);
- } /* ptk_equal */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint ptk_point(C(Pfloat) x, C(Pfloat) y)
- PreANSI(Pfloat x)
- PreANSI(Pfloat y)
- /*
- ** \parambegin
- ** \param{Pfloat}{x}{x coordinate}{IN}
- ** \param{Pfloat}{y}{y coordinate}{IN}
- ** \paramend
- ** \blurb{This function returns a structure representing the
- ** 2D point \pardesc{(x,y)}.}
- */
- {
- Ppoint temp;
-
- temp.x = x;
- temp.y = y;
- return temp;
- } /* ptk_point */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_point3(C(Pfloat) x, C(Pfloat) y, C(Pfloat) z)
- PreANSI(Pfloat x)
- PreANSI(Pfloat y)
- PreANSI(Pfloat z)
- /*
- ** \parambegin
- ** \param{Pfloat}{x}{x coordinate}{IN}
- ** \param{Pfloat}{y}{y coordinate}{IN}
- ** \param{Pfloat}{z}{z coordinate}{IN}
- ** \paramend
- ** \blurb{This function returns a structure representing
- ** the 3D point \pardesc{(x,y,z)}.}
- */
- {
- Ppoint3 temp;
-
- temp.x = x;
- temp.y = y;
- temp.z = z;
- return temp;
- } /* ptk_point3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Pvec ptk_vector(C(Pfloat) x, C(Pfloat) y)
- PreANSI(Pfloat x)
- PreANSI(Pfloat y)
- /*
- ** \parambegin
- ** \param{Pfloat}{x}{x coordinate}{IN}
- ** \param{Pfloat}{y}{y coordinate}{IN}
- ** \paramend
- ** \blurb{This function returns a structure representing
- ** the 2D vector \pardesc{(x,y)}.}
- */
- {
- Pvec temp;
-
- temp.delta_x = x;
- temp.delta_y = y;
- return temp;
- } /* ptk_vector */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Pvec3 ptk_vector3(C(Pfloat) x, C(Pfloat) y, C(Pfloat) z)
- PreANSI(Pfloat x)
- PreANSI(Pfloat y)
- PreANSI(Pfloat z)
- /*
- ** \parambegin
- ** \param{Pfloat}{x}{x coordinate}{IN}
- ** \param{Pfloat}{y}{y coordinate}{IN}
- ** \param{Pfloat}{z}{z coordinate}{IN}
- ** \paramend
- ** \blurb{This function returns a structure representing
- ** the 3D vector \pardesc{(x,y,z)}.}
- */
- {
- Pvec3 temp;
-
- temp.delta_x = x;
- temp.delta_y = y;
- temp.delta_z = z;
- return temp;
- } /* ptk_vector3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Plimit ptk_limit(C(Pfloat) xmin, C(Pfloat) xmax, C(Pfloat) ymin,
- C(Pfloat) ymax)
- PreANSI(Pfloat xmin)
- PreANSI(Pfloat xmax)
- PreANSI(Pfloat ymin)
- PreANSI(Pfloat ymax)
- /*
- ** \parambegin
- ** \param{Pfloat}{xmin}{minimum x coordinate}{IN}
- ** \param{Pfloat}{xmax}{maximum x coordinate}{IN}
- ** \param{Pfloat}{ymin}{minimum y coordinate}{IN}
- ** \param{Pfloat}{ymax}{maximum y coordinate}{IN}
- ** \paramend
- ** \blurb{This function returns a structure representing the 2D
- ** rectangle whose corners are defined by \pardesc{xmin, xmax, ymin, ymax}.}
- */
- {
- Plimit temp;
-
- temp.x_min = xmin;
- temp.x_max = xmax;
- temp.y_min = ymin;
- temp.y_max = ymax;
- return temp;
- } /* ptk_limit */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Plimit3 ptk_limit3(C(Pfloat) xmin, C(Pfloat) xmax, C(Pfloat) ymin,
- C(Pfloat) ymax, C(Pfloat) zmin, C(Pfloat) zmax)
- PreANSI(Pfloat xmin)
- PreANSI(Pfloat xmax)
- PreANSI(Pfloat ymin)
- PreANSI(Pfloat ymax)
- PreANSI(Pfloat zmin)
- PreANSI(Pfloat zmax)
- /*
- ** \parambegin
- ** \param{Pfloat}{xmin}{minimum x coordinate}{IN}
- ** \param{Pfloat}{xmax}{maximum x coordinate}{IN}
- ** \param{Pfloat}{ymin}{minimum y coordinate}{IN}
- ** \param{Pfloat}{ymax}{maximum y coordinate}{IN}
- ** \param{Pfloat}{zmin}{minimum z coordinate}{IN}
- ** \param{Pfloat}{zmax}{maximum z coordinate}{IN}
- ** \paramend
- ** \blurb{This function returns a structure representing the
- ** 3D volume defined by \pardesc{xmin, xmax, ymin, ymax, zmin, zmax}.}
- */
- {
- Plimit3 temp;
-
- temp.x_min = xmin;
- temp.x_max = xmax;
- temp.y_min = ymin;
- temp.y_max = ymax;
- temp.z_min = zmin;
- temp.z_max = zmax;
- return temp;
- } /* ptk_limit3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_vec3topt3(C(Pvec3 *) vec)
- PreANSI(Pvec3 *vec)
- /*
- ** \parambegin
- ** \param{Pvec3 *}{vec}{3D vector}{IN}
- ** \paramend
- ** \blurb{This function convert the 3D vector \pardesc{vec} to a 3D point.}
- */
- {
- Ppoint3 temp;
-
- temp = ptk_point3(vec->delta_x, vec->delta_y, vec->delta_z);
- return temp;
- } /* ptk_vec3topt3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Pvec3 ptk_pt3tovec3(C(Ppoint3 *) pt)
- PreANSI(Ppoint3 *pt)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{pt}{3D point}{IN}
- ** \paramend
- ** \blurb{This function converts the 3D point \pardesc{pt} to a 3D vector.}
- */
- {
- Pvec3 temp;
-
- temp = ptk_vector3(pt->x, pt->y, pt->z);
- return temp;
- } /* ptk_pt3tovec3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Pfloat ptk_dotv3(C(Ppoint3 *) v1, C(Ppoint3 *) v2)
- PreANSI(Ppoint3 *v1)
- PreANSI(Ppoint3 *v2)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{v1}{3D vector}{IN}
- ** \param{Ppoint3 *}{v2}{3D vector}{IN}
- ** \paramend
- ** \blurb{This function evaluates the dot product of the
- ** two 3D vectors \pardesc{v1} and
- ** \pardesc{v2}, returning it as the value of the function.}
- */
- {
- return (v1->x * v2->x + v1->y * v2->y + v1->z * v2->z);
- } /* ptk_dotv3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Pfloat ptk_dotv(C(Ppoint *) v1, C(Ppoint *) v2)
- PreANSI(Ppoint *v1)
- PreANSI(Ppoint *v2)
- /*
- ** \parambegin
- ** \param{Ppoint *}{v1}{2D vector}{IN}
- ** \param{Ppoint *}{v2}{2D vector}{IN}
- ** \paramend
- ** \blurb{Evaluates the dot product of the two 2D vectors \pardesc{v1} and
- ** \pardesc{v2}, returning it as the value of the function.}
- */
- {
- return (v1->x * v2->x + v1->y * v2->y);
- } /* ptk_dotv */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_crossv3(C(Ppoint3 *) v1, C(Ppoint3 *) v2)
- PreANSI(Ppoint3 *v1)
- PreANSI(Ppoint3 *v2)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{v1}{3D vector}{IN}
- ** \param{Ppoint3 *}{v2}{3D vector}{IN}
- ** \paramend
- ** \blurb{This function evaluates the cross product of
- ** the two 3D vectors \pardesc{v1} and
- ** \pardesc{v2}, returning the new vector as
- ** the function result. Since a local copy is made statements such as
- ** {\tt v2 == ptk\_crossv(v1, v2)}
- ** will produce the correct answer.}
- */
- {
- Ppoint3 temp;
-
- temp.x = v1->y * v2->z - v1->z * v2->y;
- temp.y = v1->z * v2->x - v1->x * v2->z;
- temp.z = v1->x * v2->y - v1->y * v2->x;
- return temp;
- } /* ptk_crossv3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern ptkboolean ptk_nullv3(C(Ppoint3 *) vec)
- PreANSI(Ppoint3 *vec)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{vec}{3D vector}{IN}
- ** \paramend
- ** \blurb{This function returns \pardesc{TRUE} if the modulus
- ** of the 3D vector\pardesc{vec}
- ** is less than the global tolerance \pardesc{ptkpceps}, otherwise
- ** \pardesc{FALSE}.}
- */
- {
- return (ptk_equal(vec->x, 0.0) && ptk_equal(vec->y, 0.0) &&
- ptk_equal(vec->z, 0.0));
- } /* ptk_nullv3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern ptkboolean ptk_nullv(C(Ppoint *) vec)
- PreANSI(Ppoint *vec)
- /*
- ** \parambegin
- ** \param{Ppoint *}{vec}{2D vector}{IN}
- ** \paramend
- ** \blurb{This function returns \pardesc{TRUE} if the
- ** modulus of the 2D vector \pardesc{vec}
- ** is less than the global tolerance \pardesc{ptkpceps}, otherwise
- ** \pardesc{FALSE}.}
- */
- {
- return (ptk_equal(vec->x, 0.0) && ptk_equal(vec->y, 0.0));
- } /* ptk_nullv */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Pfloat ptk_modv3(C(Ppoint3 *) vec)
- PreANSI(Ppoint3 *vec)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{vec}{3D vector}{IN}
- ** \paramend
- ** \blurb{Returns the modulus of the vector \pardesc{vec}.}
- */
- {
- return sqrt(vec->x * vec->x + vec->y * vec->y + vec->z * vec->z);
- } /* ptk_modv3 */
-
- /*-------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Pfloat ptk_modv(C(Ppoint *) vec)
- PreANSI(Ppoint *vec)
- /*
- ** \parambegin
- ** \param{Ppoint *}{vec}{2D vector}{IN}
- ** \paramend
- ** \blurb{This function returns the modulus of the 2D vector \pardesc{vec}.}
- */
- {
- return sqrt(vec->x * vec->x + vec->y * vec->y);
- } /* ptk_modv */
-
- /*-------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_unitv3(C(Ppoint3 *) vec)
- PreANSI(Ppoint3 *vec)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{vec}{3D vector}{IN}
- ** \paramend
- ** \blurb{This function generates and returns a unit
- ** vector from the supplied 3D vector
- ** \pardesc{vec}.}
- */
- {
- Pfloat modu;
- Ppoint3 temp;
-
- modu = ptk_modv3(vec);
- if (!ptk_equal(modu, 0.0))
- {
- temp = ptk_point3(vec->x / modu, vec->y / modu, vec->z / modu);
- return temp;
- }
- else
- {
- temp = ptk_point3(0.0, 0.0, 0.0);
- return temp;
- }
- } /* ptk_unitv3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint ptk_unitv(C(Ppoint *) vec)
- PreANSI(Ppoint *vec)
- /*
- ** \parambegin
- ** \param{Ppoint *}{vec}{2D vector}{IN}
- ** \paramend
- ** \blurb{This function generates and returns a unit vector from
- ** the supplied 2D vector
- ** \pardesc{vec}.}
- */
- {
- Pfloat modu;
- Ppoint temp;
-
- modu = ptk_modv(vec);
- if (!ptk_equal(modu, 0.0))
- {
- temp = ptk_point(vec->x / modu, vec->y / modu);
- return temp;
- }
- else
- {
- temp = ptk_point(0.0, 0.0);
- return temp;
- }
- } /* ptk_unitv */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_scalev3(C(Ppoint3 *) vec, C(Pfloat) scale)
- PreANSI(Ppoint3 *vec)
- PreANSI(Pfloat scale)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{vec}{3D vector}{IN}
- ** \param{Pfloat}{scale}{scale factor}{IN}
- ** \paramend
- ** \blurb{This function multiplies the 3D vector \pardesc{v}
- ** by the scalar \pardesc{s} and
- ** returns the result.}
- */
- {
- Ppoint3 temp;
-
- temp = ptk_point3(vec->x * scale, vec->y * scale, vec->z * scale);
- return temp;
- } /* ptk_scalev3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint ptk_scalev(C(Ppoint *) vec, C(Pfloat) scale)
- PreANSI(Ppoint *vec)
- PreANSI(Pfloat scale)
- /*
- ** \parambegin
- ** \param{Ppoint *}{vec}{2D vector}{IN}
- ** \param{Pfloat}{scale}{scale factor}{IN}
- ** \paramend
- ** \blurb{This function multiplies the 2D vector
- ** \pardesc{v} by the scalar \pardesc{s} and
- ** returns the result.}
- */
- {
- Ppoint temp;
-
- temp = ptk_point(vec->x * scale, vec->y * scale);
- return temp;
- } /* ptk_scalev */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_subv3(C(Ppoint3 *) p1, C(Ppoint3 *) p2)
- PreANSI(Ppoint3 *p1)
- PreANSI(Ppoint3 *p2)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{p1}{3D vector}{IN}
- ** \param{Ppoint3 *}{p2}{3D vector}{IN}
- ** \paramend
- ** \blurb{This function evaluates the 3D vector \pardesc {v1-v2}.}
- */
- {
- Ppoint3 v;
-
- v = ptk_point3(p1->x - p2->x, p1->y - p2->y, p1->z - p2->z);
- return v;
- } /* ptk_subv3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint ptk_subv(C(Ppoint *) p1, C(Ppoint *) p2)
- PreANSI(Ppoint *p1)
- PreANSI(Ppoint *p2)
- /*
- ** \parambegin
- ** \param{Ppoint *}{p1}{2D vector}{IN}
- ** \param{Ppoint *}{p2}{2D vector}{IN}
- ** \paramend
- ** \blurb{This function evaluates the 2D vector \pardesc {v1-v2}.}
- */
- {
- Ppoint v;
-
- v = ptk_point(p1->x - p2->x, p1->y - p2->y);
- return v;
- } /* ptk_subv */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_addv3(C(Ppoint3 *) p1, C(Ppoint3 *) p2)
- PreANSI(Ppoint3 *p1)
- PreANSI(Ppoint3 *p2)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{p1}{3D vector}{IN}
- ** \param{Ppoint3 *}{p2}{3D vector}{IN}
- ** \paramend
- ** \blurb{This function adds the two 3D vectors \pardesc{v1} and \pardesc{v2},
- ** and returns the result.}
- */
- {
- Ppoint3 v;
-
- v = ptk_point3(p1->x + p2->x, p1->y + p2->y, p1->z + p2->z);
- return v;
- } /* ptk_addv3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint ptk_addv(C(Ppoint *) p1, C(Ppoint *) p2)
- PreANSI(Ppoint *p1)
- PreANSI(Ppoint *p2)
- /*
- ** \parambegin
- ** \param{Ppoint *}{p1}{2D vector}{IN}
- ** \param{Ppoint *}{p2}{2D vector}{IN}
- ** \paramend
- ** \blurb{This function adds the two 2D vectors \pardesc{v1}
- ** and \pardesc{v2}, and returns the result.}
- */
- {
- Ppoint v;
-
- v = ptk_point(p1->x + p2->x, p1->y + p2->y);
- return v;
- } /* ptk_addv */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_unitmatrix(C(Pmatrix) matrix)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix}{matrix}{3x3 matrix}{IN}
- ** \paramend
- ** \blurb{This procedure creates a unit $3\times 3$ matrix, and stores it in
- ** \pardesc{matrix}.}
- */
- {
- /* */
- Pint jj, ii;
-
- for (ii = 0; ii <= 2; ii++)
- {
- for (jj = 0; jj <= 2; jj++)
- matrix[ii][jj] = 0.0;
- matrix[ii][ii] = 1.0;
- }
- } /* ptk_unitmatrix */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_unitmatrix3(C(Pmatrix3) matrix)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{IN}
- ** \paramend
- ** \blurb{This procedure creates a unit $4\times 4$ matrix, and stores it in
- ** \pardesc{matrix}.}
- */
- {
- /* */
- Pint jj, ii;
-
- for (ii = 0; ii <= 3; ii++)
- {
- for (jj = 0; jj <= 3; jj++)
- matrix[ii][jj] = 0.0;
- matrix[ii][ii] = 1.0;
- }
- } /* ptk_unitmatrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_transposematrix3(C(Pmatrix3) matrix, C(Pmatrix3) result)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Pmatrix3 result)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{IN}
- ** \param{Pmatrix3}{result}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function transposes \pardesc{matrix}, and returns the resul
- ** in \pardesc{result}.
- ** Note that \pardesc{restut} can be the same variable
- ** as \pardesc{matrix} since a copy is made
- ** first.}
- */
- {
- Pmatrix3 temp;
- Pint i, j;
-
- memcpy(temp, matrix, sizeof(Pmatrix3));
- for (i = 0; i <= 3; i++)
- {
- for (j = 0; j <= 3; j++)
- result[i][j] = temp[j][i];
- }
- } /* ptk_transposematrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_transposematrix(C(Pmatrix) matrix, C(Pmatrix) result)
- PreANSI(Pmatrix matrix)
- PreANSI(Pmatrix result)
- /*
- ** \parambegin
- ** \param{Pmatrix}{matrix}{3x3 matrix}{IN}
- ** \param{Pmatrix}{result}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function transposes \pardesc{matrix}, and returns the resul
- ** in \pardesc{result}.
- ** Note that \pardesc{restut} can be the same variable
- ** as \pardesc{matrix} since a copy is made
- ** first.}
- */
- {
- Pmatrix temp;
- Pint i, j;
-
- memcpy(temp, matrix, sizeof(Pmatrix));
- for (i = 0; i <= 2; i++)
- {
- for (j = 0; j <= 2; j++)
- result[i][j] = temp[j][i];
- }
- } /* ptk_transposematrix */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_multiplymatrix3(C(Pmatrix3) matrix1, C(Pmatrix3) matrix2,
- C(Pmatrix3) result)
- PreANSI(Pmatrix3 matrix1)
- PreANSI(Pmatrix3 matrix2)
- PreANSI(Pmatrix3 result)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix1}{4x4 matrix}{IN}
- ** \param{Pmatrix3}{matrix2}{4x4 matrix}{IN}
- ** \param{Pmatrix3}{result}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function makes \pardesc{result} the product of
- ** the $4 \times 4$ matrices \pardesc{matrix1} and
- ** \pardesc{matrix2}, with {\tt result $\leftarrow$ matrix1 * matrix2}.
- ** Note that \pardesc{result} can also be \pardesc{matrix1} or \pardesc{matrix2}
- ** since a copy is made.
- ** This function uses Winograd's method, see "Handbook of Algorithms
- ** and Data Structures", G.H. Gonnet, Addison Wesley.}
- */
- {
- Pint ii, jj;
- Pmatrix3 sum;
- Pfloat temp;
- Pfloat d[4], e[4];
-
- for (ii = 0; ii <= 3; ii++)
- {
- d[ii] = (matrix1[ii][1] * matrix1[ii][0]) +
- (matrix1[ii][3] * matrix1[ii][2]);
- e[ii] = (matrix2[0][ii] * matrix2[1][ii]) +
- (matrix2[2][ii] * matrix2[3][ii]);
- }
-
- for (ii = 0; ii <= 3; ii++)
- {
- for (jj = 0; jj <= 3; jj++)
- {
- temp = (matrix1[ii][1] + matrix2[0][jj]) *
- (matrix1[ii][0] + matrix2[1][jj]);
- temp += (matrix1[ii][3] + matrix2[2][jj]) *
- (matrix1[ii][2] + matrix2[3][jj]) - d[ii] - e[jj];
- sum[ii][jj] = temp;
- }
- }
- /* copy matrix back in case result is one of the other two */
- memcpy(result, sum, sizeof(Pmatrix3));
- } /* ptk_multiplymatrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_multiplymatrix(C(Pmatrix) matrix1, C(Pmatrix) matrix2,
- C(Pmatrix) result)
- PreANSI(Pmatrix matrix1)
- PreANSI(Pmatrix matrix2)
- PreANSI(Pmatrix result)
- /*
- ** \parambegin
- ** \param{Pmatrix}{matrix1}{3x3 matrix}{IN}
- ** \param{Pmatrix}{matrix2}{3x3 matrix}{IN}
- ** \param{Pmatrix}{result}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function makes \pardesc{result} the product of the
- ** $3 \times 3$ matrices \pardesc{matrix1} and
- ** \pardesc{matrix2}, with {\tt result $\leftarrow$ matrix1 * matrix2}.
- ** Note that \pardesc{result} can also be \pardesc{matrix1} or \pardesc{matrix2}
- ** since a copy is made.}
- */
- {
- Pint ii, jj, kk;
- Pmatrix sum;
- Pfloat temp;
- Pfloat d[3], e[3];
-
- for (ii = 0; ii <= 2; ii++)
- for (jj = 0; jj <= 2; jj++)
- sum[ii][jj] = 0.0;
- for (ii = 0; ii <= 2; ii++)
- for (jj = 0; jj <= 2; jj++)
- for (kk = 0; kk <= 2; kk++)
- sum[ii][jj] += (matrix1[ii][kk] * matrix2[kk][jj]);
-
- /* for (ii = 0; ii <= 2; ii++)
- {
- d[ii] = (matrix1[ii][1] * matrix1[ii][0]);
- e[ii] = (matrix2[0][ii] * matrix2[1][ii]);
- }
- for (ii = 0; ii <= 2; ii++)
- {
- for (jj = 0; jj <= 2; jj++)
- {
- temp = (matrix1[ii][1] + matrix2[0][jj]) *
- (matrix1[ii][0] + matrix2[1][jj]);
- temp += (matrix1[ii][2] * matrix2[2][2]) - d[ii] - e[jj];
- sum[ii][jj] = temp;
- }
- }
- */
- /* copy matrix back in case result is one of the other two */
- memcpy(result, sum, sizeof(Pmatrix));
- } /* ptk_multiplymatrix */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_concatenatematrix3(C(Pcompose_type) operation,
- C(Pmatrix3) matrix1, C(Pmatrix3) matrix2, C(Pmatrix3) result)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix1)
- PreANSI(Pmatrix3 matrix2)
- PreANSI(Pmatrix3 result)
- /*
- ** \parambegin
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix1}{4x4 matrix}{IN}
- ** \param{Pmatrix3}{matrix2}{4x4 matrix}{IN}
- ** \param{Pmatrix3}{result}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function concatenates the $4 \times 4$ matrices
- ** \pardesc{matrix1} and \pardesc{matrix2}
- ** on the basis of \pardesc{operation}.
- ** The result is stored in \pardesc{result}.
- ** Note that \pardesc{result} can also be \pardesc{matrix1} or \pardesc{matrix2}
- ** since a copy is made. When \pardesc{operation} is
- ** \pardesc{preconcatenate}, then \pardesc{result $\leftarrow$ matrix2 * matrix1}.
- ** When \pardesc{operation} is \pardesc{postconcatenate},
- ** \pardesc{result $\leftarrow$ matrix1 * matrix2}.}
- */
- {
- switch (operation)
- {
- case PTYPE_PRECONCAT:
- ptk_multiplymatrix3(matrix2, matrix1, result);
- break;
-
- case PTYPE_POSTCONCAT:
- ptk_multiplymatrix3(matrix1, matrix2, result);
- break;
-
- case PTYPE_REPLACE:
- memcpy(result, matrix1, sizeof(Pmatrix3));
- break;
- }
- } /* ptk_concatenatematrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_concatenatematrix(C(Pcompose_type) operation,
- C(Pmatrix) matrix1, C(Pmatrix) matrix2, C(Pmatrix) result)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix1)
- PreANSI(Pmatrix matrix2)
- PreANSI(Pmatrix result)
- /*
- ** \parambegin
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix1}{3x3 matrix}{IN}
- ** \param{Pmatrix}{matrix2}{3x3 matrix}{IN}
- ** \param{Pmatrix}{result}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function concatenates
- ** the $3 \times 3$ matrices \pardesc{matrix1} and \pardesc{matrix2}
- ** on the basis of \pardesc{operation}.
- ** The result is stored in \pardesc{result}.
- ** Note that \pardesc{result} can also be \pardesc{matrix1} or \pardesc{matrix2}
- ** since a copy is made. When \pardesc{operation} is
- ** \pardesc{preconcatenate}, then \pardesc{result $\leftarrow$ matrix2 * matrix1}.
- ** When \pardesc{operation} is \pardesc{postconcatenate},
- ** \pardesc{result $\leftarrow$ matrix1 * matrix2}.}
- */
- {
- switch (operation)
- {
- case PTYPE_PRECONCAT:
- ptk_multiplymatrix(matrix2, matrix1, result);
- break;
-
- case PTYPE_POSTCONCAT:
- ptk_multiplymatrix(matrix1, matrix2, result);
- break;
-
- case PTYPE_REPLACE:
- memcpy(result, matrix1, sizeof(Pmatrix));
- break;
- }
- } /* ptk_concatenatematrix */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_shift3(C(Ppoint3 *) shift, C(Pcompose_type) operation,
- C(Pmatrix3) matrix)
- PreANSI(Ppoint3 *shift)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{shift}{shift factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the specified 3D shift and concatenates
- ** this matrix with \pardesc{matrix} on the basis of \pardesc{operation}.}
- */
- {
- Pmatrix3 temp;
-
- ptk_unitmatrix3(temp);
- temp[0][3] = shift->x;
- temp[1][3] = shift->y;
- temp[2][3] = shift->z;
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_shift3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_shift(C(Ppoint *) shift, C(Pcompose_type) operation,
- C(Pmatrix) matrix)
- PreANSI(Ppoint *shift)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Ppoint *}{shift}{shift factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the specified 2D shift and concatenates
- ** this matrix with \pardesc{matrix} on the basis of \pardesc{operation}.}
- */
- {
- Pmatrix temp;
-
- ptk_unitmatrix(temp);
- temp[0][2] = shift->x;
- temp[1][2] = shift->y;
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_shift */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_scale3(C(Ppoint3 *) scale, C(Pcompose_type) operation,
- C(Pmatrix3) matrix)
- PreANSI(Ppoint3 *scale)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{shift}{shift factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function
- ** computes a matrix to perform the specified 3D scale and concatenates
- ** this with \pardesc{matrix} on the basis of \pardesc{operation}.}
- */
- {
- Pmatrix3 temp;
-
- ptk_unitmatrix3(temp);
- temp[0][0] = scale->x;
- temp[1][1] = scale->y;
- temp[2][2] = scale->z;
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_scale3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_scale(C(Ppoint *) scale, C(Pcompose_type) operation,
- C(Pmatrix) matrix)
- PreANSI(Ppoint *scale)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Ppoint *}{shift}{shift factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the specified 2D scale and concatenates
- ** this matrix with \pardesc{matrix} on the basis of \pardesc{operation}.}
- */
- {
- Pmatrix temp;
-
- ptk_unitmatrix(temp);
- temp[0][0] = scale->x;
- temp[1][1] = scale->y;
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_scale */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotatecs3(C(Pfloat) costheta, C(Pfloat) sinetheta,
- C(ptkeaxistype) axis, C(Pcompose_type) operation,
- C(Pmatrix3) matrix)
- PreANSI(Pfloat costheta)
- PreANSI(Pfloat sinetheta)
- PreANSI(ptkeaxistype axis)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Pfloat}{costheta}{cosine of angle}{IN}
- ** \param{Pfloat}{sinetheta}{sine of angle}{IN}
- ** \param{ptkeaxistype}{axis}{x, y or z axis}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the specified 3D rotation and concatenates
- ** this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** This form assumes that the rotation is specified
- ** using the $\cos(theta)$ and $\sin(theta)$ terms.
- ** Note that no check is made to ensure that the sum of the squares of these
- ** terms is 1.}
- */
- {
- Pmatrix3 temp;
-
- ptk_unitmatrix3(temp);
- switch (axis)
- {
- case PTKEXAXIS:
- temp[2][2] = costheta;
- temp[1][1] = costheta;
- temp[1][2] = -sinetheta;
- temp[2][1] = sinetheta;
- break;
-
- case PTKEYAXIS:
- temp[0][0] = costheta;
- temp[2][2] = costheta;
- temp[0][2] = sinetheta;
- temp[2][0] = -sinetheta;
- break;
-
- case PTKEZAXIS:
- temp[0][0] = costheta;
- temp[1][1] = costheta;
- temp[0][1] = -sinetheta;
- temp[1][0] = sinetheta;
- break;
- }
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_rotatecs3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotatecs(C(Pfloat) costheta, C(Pfloat) sinetheta,
- C(ptkeaxistype) axis, C(Pcompose_type) operation,
- C(Pmatrix) matrix)
- PreANSI(Pfloat costheta)
- PreANSI(Pfloat sinetheta)
- PreANSI(ptkeaxistype axis)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Pfloat}{costheta}{cosine of angle}{IN}
- ** \param{Pfloat}{sinetheta}{sine of angle}{IN}
- ** \param{ptkeaxistype}{axis}{x, y or z axis}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the specified 2D rotation and concatenates
- ** this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** This form assumes that the rotation is specified
- ** using the $\cos(theta)$ and $\sin(theta)$ terms.
- ** Note that no check is made to ensure that the sum of the squares of these
- ** terms is 1.}
- */
- {
- Pmatrix temp;
-
- ptk_unitmatrix(temp);
- switch (axis)
- {
- case PTKEXAXIS:
- temp[2][2] = costheta;
- temp[1][1] = costheta;
- temp[1][2] = -sinetheta;
- temp[2][1] = sinetheta;
- break;
-
- case PTKEYAXIS:
- temp[0][0] = costheta;
- temp[2][2] = costheta;
- temp[0][2] = sinetheta;
- temp[2][0] = -sinetheta;
- break;
-
- case PTKEZAXIS:
- temp[0][0] = costheta;
- temp[1][1] = costheta;
- temp[0][1] = -sinetheta;
- temp[1][0] = sinetheta;
- break;
- }
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_rotatecs */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotate3(C(Pfloat) rotation, C(ptkeaxistype) axis,
- C(Pcompose_type) operation, C(Pmatrix3) matrix)
- PreANSI(Pfloat rotation)
- PreANSI(ptkeaxistype axis)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Pfloat}{rotation}{angle in degrees}{IN}
- ** \param{ptkeaxistype}{axis}{x, y or z axis}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the specified 3D rotation and concatenates
- ** this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** \pardesc{rotation} is expressed in degrees.}
- */
- {
- Pfloat costheta;
- Pfloat sinetheta;
-
- costheta = cos((rotation * ptkcdtor));
- sinetheta = sin((rotation * ptkcdtor));
- ptk_rotatecs3(costheta, sinetheta, axis, operation, matrix);
- } /* ptk_rotate3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotate(C(Pfloat) rotation, C(ptkeaxistype) axis,
- C(Pcompose_type) operation, C(Pmatrix) matrix)
- PreANSI(Pfloat rotation)
- PreANSI(ptkeaxistype axis)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Pfloat}{rotation}{angle in degrees}{IN}
- ** \param{ptkeaxistype}{axis}{x, y or z axis}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the specified 2D rotation and concatenates
- ** this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** \pardesc{rotation} is expressed in degrees.}
- */
- {
- Pfloat costheta;
- Pfloat sinetheta;
-
- costheta = cos((rotation * ptkcdtor));
- sinetheta = sin((rotation * ptkcdtor));
- ptk_rotatecs(costheta, sinetheta, axis, operation, matrix);
- } /* ptk_rotate */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_shear3(C(ptkeaxistype) shearaxis, C(ptkeaxistype) sheardir,
- C(Pfloat) shearfactor, C(Pcompose_type) operation,
- C(Pmatrix3) matrix)
- PreANSI(ptkeaxistype shearaxis)
- PreANSI(ptkeaxistype sheardir)
- PreANSI(Pfloat shearfactor)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{ptkeaxistype}{shearaxis}{x, y or z axis}{IN}
- ** \param{ptkeaxistype}{sheardir}{x, y or z direction}{IN}
- ** \param{Pfloat}{shearfactor}{shear factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes a matrix to perform the specified 3D
- ** shear and concatenates
- ** this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** The shear is specified as an amount \pardesc{f} about axis \pardesc{i}
- ** in direction \pardesc{j}.}
- */
- {
- Pmatrix3 temp;
-
- ptk_unitmatrix3(temp);
- temp[(Pint)shearaxis - 1][(Pint)sheardir - 1] = shearfactor;
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_shear3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_shear(C(ptkeaxistype) shearaxis, C(ptkeaxistype) sheardir,
- C(Pfloat) shearfactor, C(Pcompose_type) operation,
- C(Pmatrix) matrix)
- PreANSI(ptkeaxistype shearaxis)
- PreANSI(ptkeaxistype sheardir)
- PreANSI(Pfloat shearfactor)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{ptkeaxistype}{shearaxis}{x or y axis}{IN}
- ** \param{ptkeaxistype}{sheardir}{x or y direction}{IN}
- ** \param{Pfloat}{shearfactor}{shear factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes a matrix to perform the specified 2D
- ** shear and concatenates
- ** this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** The shear is specified as an amount \pardesc{f} about axis \pardesc{i}
- ** in direction \pardesc{j}.}
- */
- {
- Pmatrix temp;
-
- ptk_unitmatrix(temp);
- temp[(Pint)shearaxis - 1][(Pint)sheardir - 1] = shearfactor;
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_shear */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotatevv3(C(Ppoint3 *) v1, C(Ppoint3 *) v2,
- C(Pcompose_type) operation,
- C(Pmatrix3) matrix, C(Pint *)error)
- PreANSI(Ppoint3 *v1)
- PreANSI(Ppoint3 *v2)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{v1}{3D vector}{IN}
- ** \param{Ppoint3 *}{v2}{3D vector}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the rotation (about the origin) of the 3D vector
- ** \pardesc{v1} to the 3D vector
- ** \pardesc{v2}, and concatenates this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation} (\cite{rog:mecg},
- ** pages 55--59). If the parameters are invalid, \pardesc{error} is set to
- ** -1. Otherwise, its value is \pardesc{ptkcpcok}.}
- */
- {
- Pmatrix3 temp;
- Ppoint3 dv1, dv2, nvec;
- Pfloat t1, costheta, sinetheta;
-
- /* Create a rotation matrix (about origin) to rotate from
- ** vector dv1 to vector dv2
- ** Cf ROGERS and ADAMS page 55-59
- */
-
- *error = ptkcpcok; /* Assume OK */
- dv1 = ptk_unitv3(v1);
- dv2 = ptk_unitv3(v2);
-
- /* Get sine theta (cross product) and cos theta (dot product) */
-
- costheta = dv1.x * dv2.x + dv1.y * dv2.y + dv1.z * dv2.z;
- nvec = ptk_crossv3(&dv1, &dv2);
-
- /* How do I choose sign of sinetheta?
- ** let A, B and K be unit vectors, then
- ** A X B := sin(theta) K
- ** The sign of sinetheta is not important
- ** because of the way it appears in the subsequent formulae
- */
-
- sinetheta = ptk_modv3(&nvec);
- if (ptk_equal(fabs(sinetheta), 0.0))
- {
- *error = -1;
- sinetheta = ptkcpceps;
- }
- nvec = ptk_unitv3(&nvec);
- ptk_unitmatrix3(temp); /* get a unit matrix */
- t1 = 1.0 - costheta;
- temp[0][0] = (nvec.x * nvec.x) + (1.0 - (nvec.x * nvec.x)) * costheta;
- temp[1][1] = (nvec.y * nvec.y) + (1.0 - (nvec.y * nvec.y)) * costheta;
- temp[2][2] = (nvec.z * nvec.z) + (1.0 - (nvec.z * nvec.z)) * costheta;
- temp[1][0] = (nvec.x * nvec.y * t1) + (nvec.z * sinetheta);
- temp[2][0] = (nvec.x * nvec.z * t1) - (nvec.y * sinetheta);
- temp[0][1] = (nvec.x * nvec.y * t1) - (nvec.z * sinetheta);
- temp[2][1] = (nvec.y * nvec.z * t1) + (nvec.x * sinetheta);
- temp[0][2] = (nvec.x * nvec.z * t1) + (nvec.y * sinetheta);
- temp[1][2] = (nvec.y * nvec.z * t1) - (nvec.x * sinetheta);
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_rotatevv3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotatevv(C(Ppoint *) v1, C(Ppoint *) v2,
- C(Pcompose_type) operation,
- C(Pmatrix) matrix, C(Pint *)error)
- PreANSI(Ppoint *v1)
- PreANSI(Ppoint *v2)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Ppoint *}{v1}{2D vector}{IN}
- ** \param{Ppoint *}{v2}{2D vector}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform the rotation (about the origin) of the 3D vector
- ** \pardesc{v1} to the 3D vector
- ** \pardesc{v2}, and concatenates this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation} (\cite{rog:mecg},
- ** pages 55--59). If the parameters are invalid, \pardesc{error} is set to
- ** -1. Otherwise, its value is \pardesc{ptkcpcok}.}
- */
- {
- Pmatrix temp;
- Ppoint dv1, dv2, nvec;
- Pfloat t1, costheta, sinetheta;
-
- /* Create a rotation matrix (about origin) to rotate from
- ** vector dv1 to vector dv2
- ** Cf ROGERS and ADAMS page 55-59
- */
-
- *error = ptkcpcok; /* Assume OK */
- dv1 = ptk_unitv(v1);
- dv2 = ptk_unitv(v2);
-
- /* Get sine theta (cross product) and cos theta (dot product) */
-
- costheta = dv1.x * dv2.x + dv1.y * dv2.y;
- nvec = ptk_point(0.0, 0.0);
-
- /* How do I choose sign of sinetheta?
- ** let A, B and K be unit vectors, then
- ** A X B := sin(theta) K
- ** The sign of sinetheta is not important
- ** because of the way it appears in the subsequent formulae
- */
-
- sinetheta = ptk_modv(&nvec);
- if (ptk_equal(fabs(sinetheta), 0.0))
- {
- *error = -1;
- sinetheta = ptkcpceps;
- }
- nvec = ptk_unitv(&nvec);
- ptk_unitmatrix(temp); /* get a unit matrix */
- t1 = 1.0 - costheta;
- temp[0][0] = (nvec.x * nvec.x) + (1.0 - (nvec.x * nvec.x)) * costheta;
- temp[1][1] = (nvec.y * nvec.y) + (1.0 - (nvec.y * nvec.y)) * costheta;
- temp[2][2] = costheta;
- temp[1][0] = (nvec.x * nvec.y * t1);
- temp[2][0] = (nvec.y * sinetheta);
- temp[0][1] = (nvec.x * nvec.y * t1);
- temp[2][1] = (nvec.x * sinetheta);
- temp[0][2] = (nvec.y * sinetheta);
- temp[1][2] = (nvec.x * sinetheta);
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_rotatevv */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotateline3(C(Ppoint3 *) p1, C(Ppoint3 *) p2,
- C(Pfloat) theta, C(Pcompose_type) operation,
- C(Pmatrix3) matrix, C(Pint *)error)
- PreANSI(Ppoint3 *p1)
- PreANSI(Ppoint3 *p2)
- PreANSI(Pfloat theta)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{p1}{3D point}{IN}
- ** \param{Ppoint3 *}{p2}{3D point}{IN}
- ** \param{Pfloat}{theta}{angle in degrees}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform a 3D rotation of
- ** \pardesc{theta} degrees
- ** about the line connecting \pardesc{p1} to \pardesc{p2},
- ** and concatenates this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation} (\cite{rog:mecg},
- ** pages 55--59).
- ** If the parameters are invalid, \pardesc{error} is set to
- ** -1. Otherwise, its value is \pardesc{ptkcpcok}.}
- */
- {
- Pmatrix3 temp;
- Ppoint3 nvec, mnvec;
- Pfloat t1, costheta, sinetheta;
-
- *error = ptkcpcok;
- /* make a unit vector, i.e. direction cosines
- ** nvec = p2 - p1.
- */
- nvec = ptk_subv3(p2, p1);
- if (ptk_nullv3(&nvec)) {*error = -1;}
- nvec = ptk_unitv3(&nvec);
- costheta = cos(theta * ptkcdtor);
- sinetheta = sin(theta * ptkcdtor);
- t1 = 1.0 - costheta;
- ptk_unitmatrix3(temp); /* get a unit matrix */
- temp[0][0] = (nvec.x * nvec.x) + (1.0 - (nvec.x * nvec.x)) * costheta;
- temp[1][1] = (nvec.y * nvec.y) + (1.0 - (nvec.y * nvec.y)) * costheta;
- temp[2][2] = (nvec.z * nvec.z) + (1.0 - (nvec.z * nvec.z)) * costheta;
- temp[1][0] = (nvec.x * nvec.y * t1) + (nvec.z * sinetheta);
- temp[2][0] = (nvec.x * nvec.z * t1) - (nvec.y * sinetheta);
- temp[0][1] = (nvec.x * nvec.y * t1) - (nvec.z * sinetheta);
- temp[2][1] = (nvec.y * nvec.z * t1) + (nvec.x * sinetheta);
- temp[0][2] = (nvec.x * nvec.z * t1) + (nvec.y * sinetheta);
- temp[1][2] = (nvec.y * nvec.z * t1) - (nvec.x * sinetheta);
- mnvec = ptk_scalev3(p1, -1.0);
- ptk_shift3(&mnvec, PTYPE_PRECONCAT, temp);
- ptk_shift3(p1, PTYPE_POSTCONCAT, temp);
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_rotateline3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_rotateline(C(Ppoint *) p1, C(Ppoint *) p2,
- C(Pfloat) theta, C(Pcompose_type) operation,
- C(Pmatrix) matrix, C(Pint *)error)
- PreANSI(Ppoint *p1)
- PreANSI(Ppoint *p2)
- PreANSI(Pfloat theta)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Ppoint *}{p1}{2D point}{IN}
- ** \param{Ppoint *}{p2}{2D point}{IN}
- ** \param{Pfloat}{theta}{angle in degrees}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a matrix to perform a 2D rotation of
- ** \pardesc{theta} degrees
- ** about the line connecting \pardesc{p1} to \pardesc{p2},
- ** and concatenates this matrix with
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** If the parameters are invalid, \pardesc{error} is set to
- ** -1. Otherwise, its value is \pardesc{ptkcpcok}.}
- */
- {
- Pmatrix temp;
- Ppoint nvec, mnvec;
- Pfloat t1, costheta, sinetheta;
-
- *error = ptkcpcok;
- /* make a unit vector, i.e. direction cosines
- ** nvec = p2 - p1.
- */
- nvec = ptk_subv(p2, p1);
- if (ptk_nullv(&nvec)) {*error = -1;}
- nvec = ptk_unitv(&nvec);
- costheta = cos(theta * ptkcdtor);
- sinetheta = sin(theta * ptkcdtor);
- t1 = 1.0 - costheta;
- ptk_unitmatrix(temp); /* get a unit matrix */
- temp[0][0] = (nvec.x * nvec.x) + (1.0 - (nvec.x * nvec.x)) * costheta;
- temp[1][1] = (nvec.y * nvec.y) + (1.0 - (nvec.y * nvec.y)) * costheta;
- temp[2][2] = costheta;
- temp[1][0] = (nvec.x * nvec.y * t1);
- temp[2][0] = (nvec.y * sinetheta);
- temp[0][1] = (nvec.x * nvec.y * t1);
- temp[2][1] = (nvec.x * sinetheta);
- temp[0][2] = (nvec.y * sinetheta);
- temp[1][2] = (nvec.x * sinetheta);
- mnvec = ptk_scalev(p1, -1.0);
- ptk_shift(&mnvec, PTYPE_PRECONCAT, temp);
- ptk_shift(p1, PTYPE_POSTCONCAT, temp);
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_rotateline */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint4 ptk_pt3topt4(C(Ppoint3 *) point)
- PreANSI(Ppoint3 *point)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{point}{3D point}{IN}
- ** \paramend
- ** \blurb{This function converts the 3D point \pardesc{point} to a 4D point,
- ** which is returned as the result of the function. The $w$ coordinate of the
- ** 4D point is set to $1.0$.}
- */
- {
- Ppoint4 temp;
-
- temp.x = point->x;
- temp.y = point->y;
- temp.z = point->z;
- temp.w = 1.0;
- return temp;
- } /* ptk_pt3topt4 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_pt4topt3(C(Ppoint4 *) point)
- PreANSI(Ppoint4 *point)
- /*
- ** \parambegin
- ** \param{Ppoint4 *}{point}{4D point}{IN}
- ** \paramend
- ** \blurb{This function converts the 4D point \pardesc{point} to a 3D point, by
- ** dividing by $w$. The 3D point is returned as the result of the function.}
- */
- {
- Ppoint3 temp;
- Pfloat w;
-
- if (ptk_equal(fabs(point->w), 0.0))
- w = 1.0 / ptkcpceps;
- else
- w = 1.0 / point->w;
- temp.x = point->x * w;
- temp.y = point->y * w;
- temp.z = point->z * w;
- return temp;
- } /* ptk_pt4topt3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint4 ptk_transform4(C(Pmatrix3) matrix, C(Ppoint4 *) point)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Ppoint4 *point)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{IN}
- ** \param{Ppoint4 *}{point}{4D point}{IN}
- ** \paramend
- ** \blurb{This function performs the 4D transformation
- ** (that is, with no homogeneous division) of the
- ** point \pardesc{pt} by the $4 \times 4$ matrix
- ** \pardesc{matrix}, and returns the result as
- ** the value of the function.}
- */
- {
- Ppoint4 temp;
-
- temp.x = matrix[0][0] * point->x + matrix[0][1] * point->y +
- matrix[0][2] * point->z + matrix[0][3] * point->w;
- temp.y = matrix[1][0] * point->x + matrix[1][1] * point->y +
- matrix[1][2] * point->z + matrix[1][3] * point->w;
- temp.z = matrix[2][0] * point->x + matrix[2][1] * point->y +
- matrix[2][2] * point->z + matrix[2][3] * point->w;
- temp.w = matrix[3][0] * point->x + matrix[3][1] * point->y +
- matrix[3][2] * point->z + matrix[3][3] * point->w;
- return temp;
- } /* ptk_transform4 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint3 ptk_transform3(C(Pmatrix3) matrix, C(Ppoint3 *) point)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Ppoint3 *point)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{IN}
- ** \param{Ppoint3 *}{point}{3D point}{IN}
- ** \paramend
- ** \blurb{This function transforms the 3D point \pardesc{point} by
- ** the $4 \times 4$ matrix \pardesc{matrix},
- ** including homogeneous division.}
- */
- {
- Ppoint3 temp;
- Pfloat w;
-
- temp.x = matrix[0][0] * point->x + matrix[0][1] * point->y +
- matrix[0][2] * point->z + matrix[0][3];
- temp.y = matrix[1][0] * point->x + matrix[1][1] * point->y +
- matrix[1][2] * point->z + matrix[1][3];
- temp.z = matrix[2][0] * point->x + matrix[2][1] * point->y +
- matrix[2][2] * point->z + matrix[2][3];
- w = matrix[3][0] * point->x + matrix[3][1] * point->y +
- matrix[3][2] * point->z + matrix[3][3];
- if (ptk_equal(fabs(w), 0.0))
- w = 1.0 / ptkcpceps;
- else
- w = 1.0 / w;
- temp.x *= w;
- temp.y *= w;
- temp.z *= w;
- return temp;
- } /* ptk_transform3 */
-
- /*-------------------------------------------------------------------*/
-
- /*function:external*/
- extern Ppoint ptk_transform(C(Pmatrix) matrix, C(Ppoint *) point)
- PreANSI(Pmatrix matrix)
- PreANSI(Ppoint *point)
- /*
- ** \parambegin
- ** \param{Pmatrix}{matrix}{3x3 matrix}{IN}
- ** \param{Ppoint *}{point}{2D point}{IN}
- ** \paramend
- ** \blurb{This function transforms the 2D point \pardesc{point} by the
- ** $3 \times 3$ matrix \pardesc{matrix}.}
- */
- {
- Ppoint temp;
- Pfloat w;
-
- temp.x = matrix[0][0] * point->x + matrix[0][1] * point->y + matrix[0][2];
- temp.y = matrix[1][0] * point->x + matrix[1][1] * point->y + matrix[1][2];
- return temp;
- } /* ptk_transform */
-
- /*-------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_matrixtomatrix3(C(Pmatrix) mat, C(Pmatrix3) mat3)
- PreANSI(Pmatrix mat)
- PreANSI(Pmatrix mat3)
- /*
- ** \parambegin
- ** \param{Pmatrix}{mat}{3x3 matrix}{IN}
- ** \param{Pmatrix3}{mat3}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function converts the $3 \times 3$ matrix \pardesc{mat}
- ** to the $4 \times 4$ matrix \pardesc{mat3}, as follows:
- ** $$ \left( \begin{array}{ccc}
- a & b & c\\
- d & e & f\\
- g & h & j
- \end{array} \right)
-
- \rightarrow
-
- \left( \begin{array}{cccc}
- a & b & 0 & c\\
- d & e & 0 & f\\
- 0 & 0 & 1 & 0\\
- g & h & 0 & j
- \end{array} \right)
- $$}
- */
- {
- ptk_unitmatrix3(mat3);
- mat3[0][0] = mat[0][0]; /* a */
- mat3[0][1] = mat[0][1]; /* b */
- mat3[1][0] = mat[1][0]; /* d */
- mat3[1][1] = mat[1][1]; /* e */
- mat3[0][3] = mat[0][2]; /* c */
- mat3[1][3] = mat[1][2]; /* f */
- mat3[3][0] = mat[2][0]; /* g */
- mat3[3][1] = mat[2][1]; /* h */
- mat3[3][3] = mat[2][2]; /* j */
- } /* ptk_matrixtomatrix3 */
-
- /*----------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_outputmatrix3(C(FILE *) fileptr, C(Pmatrix3) matrix,
- C(char *) string)
- PreANSI(FILE *fileptr)
- PreANSI(Pmatrix3 matrix)
- PreANSI(char *string)
- /*
- ** \parambegin
- ** \param{FILE *}{fileptr}{file pointer}{OUT}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{IN}
- ** \param{char *}{string}{character string}{IN}
- ** \paramend
- ** \blurb{This function outputs the $3\times 3$ matrix
- ** \pardesc{matrix} and the message \pardesc{string}
- ** to the file specified by \pardesc{fileptr}.}
- */
- {
- Pint ii;
-
- /* Output Title */
- fprintf(fileptr,"\n*************************************************\n");
- fprintf(fileptr,"%s\n", string);
- fprintf(fileptr," 1 2 3 4\n");
- fprintf(fileptr,"-------------------------------------------------\n");
- for (ii = 0; ii <= 3; ii++)
- fprintf(fileptr,"%2ld | %11.4f%11.4f%11.4f%11.4f\n",
- ii + 1, matrix[ii][0], matrix[ii][1], matrix[ii][2],
- matrix[ii][3]);
- fprintf(fileptr,"\n*************************************************\n");
- } /* ptk_outputmatrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- static ptkboolean validbounds3(C(Plimit3 *) bound)
- PreANSI(Plimit3 *bound)
- /*
- ** \parambegin
- ** \param{Pint}{}{}{IN}
- ** \paramend
- ** description: checks if bounding box is sensibly defined (the min value
- ** is less than max value in each axis).
- ** input params: bound - 3D bounding box.
- ** output params: none.
- ** return value: TRUE if bounding box is valid, otherwise FALSE.
- */
- {
- return ((bound->x_min <= bound->x_max) && (bound->y_min <= bound->y_max) &&
- (bound->z_min <= bound->z_max));
- } /* validbounds3 */
-
- /*--------------------------------------------------------------------------*/
-
- static ptkboolean validbounds(C(Plimit *) bound)
- PreANSI(Plimit *bound)
- /*
- ** \parambegin
- ** \param{Pint}{}{}{IN}
- ** \paramend
- ** description: checks if bounding box is sensibly defined (the min value
- ** is less than max value in each axis).
- ** input params: bound - 3D bounding box.
- ** output params: none.
- ** return value: TRUE if bounding box is valid, otherwise FALSE.
- */
- {
- return ((bound->x_min <= bound->x_max) && (bound->y_min <= bound->y_max));
- } /* validbounds */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_box3tobox3(C(Plimit3 *) box1, C(Plimit3 *) box2,
- C(ptkboolean) preserve, C(Pcompose_type) operation,
- C(Pmatrix3) matrix, C(Pint *)error)
- PreANSI(Plimit3 *box1)
- PreANSI(Plimit3 *box2)
- PreANSI(ptkboolean preserve)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Plimit3 *}{box1}{3D volume}{IN}
- ** \param{Plimit3 *}{box2}{3D volume}{IN}
- ** \param{ptkboolean}{preserve}{preserve aspect ratio}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes a mapping from one 3D
- ** box to another -- a 3D window to 3D viewport
- ** transformation -- and concatenates this transformation
- ** with \pardesc{matrix} on the
- ** basis of \pardesc{operation}.If the parameters are invalid,
- ** \pardesc{error} is set to
- ** -1. Otherwise, its value is \pardesc{ptkcpcok}.}
- */
- {
- Ppoint3 vpscale, winscale;
- Pmatrix3 temp;
- Ppoint3 winmin, winmax, vpmin, vpmax, wincentre, vpcentre;
- Pfloat minscale;
-
- *error = ptkcpcok; /* assume OK */
- if (!validbounds3(box1))
- {
- *error = -1;
- return;
- }
- winmin = ptk_point3(box1->x_min, box1->y_min, box1->z_min);
- winmax = ptk_point3(box1->x_max, box1->y_max, box1->z_max);
- vpmin = ptk_point3(box2->x_min, box2->y_min, box2->z_min);
- vpmax = ptk_point3(box2->x_max, box2->y_max, box2->z_max);
-
- winscale = ptk_subv3(&winmax, &winmin);
- wincentre = ptk_scalev3(&winscale, 0.5);
- wincentre = ptk_addv3(&winmin, &wincentre);
- wincentre = ptk_scalev3(&wincentre, -1.0);
- vpscale = ptk_subv3(&vpmax, &vpmin);
- vpcentre = ptk_scalev3(&vpscale, 0.5);
- vpcentre = ptk_addv3(&vpmin, &vpcentre);
- if (winscale.x == 0.0)
- winscale.x = 1.0;
- else
- winscale.x = vpscale.x / winscale.x;
- if (winscale.y == 0.0)
- winscale.y = 1.0;
- else
- winscale.y = vpscale.y / winscale.y;
- if (winscale.z == 0.0)
- winscale.z = 1.0;
- else
- winscale.z = vpscale.z / winscale.z;
- if (preserve)
- {
- minscale = PTKMIN(winscale.x, winscale.y);
- minscale = PTKMIN(minscale, winscale.z);
- winscale = ptk_point3(minscale, minscale, minscale);
- }
- ptk_shift3(&vpcentre, PTYPE_REPLACE, temp);
- ptk_scale3(&winscale, PTYPE_PRECONCAT, temp);
- ptk_shift3(&wincentre, PTYPE_PRECONCAT, temp);
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_box3tobox3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_boxtobox(C(Plimit *) box1, C(Plimit *) box2,
- C(ptkboolean) preserve, C(Pcompose_type) operation,
- C(Pmatrix) matrix, C(Pint *)error)
- PreANSI(Plimit *box1)
- PreANSI(Plimit *box2)
- PreANSI(ptkboolean preserve)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Plimit *}{box1}{2D box}{IN}
- ** \param{Plimit *}{box2}{2D box}{IN}
- ** \param{ptkboolean}{preserve}{preserve aspect ratio}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a mapping from one 2D box to another -- a 2D window to 2D viewport
- ** transformation ---and concatenates this transformation
- ** it with \pardesc{matrix} on the
- ** basis of \pardesc{operation}.
- ** If the parameters are invalid, \pardesc{error} is set to
- ** -1. Otherwise, its value is \pardesc{ptkcpcok}.}
- */
- {
- Ppoint vpscale, winscale;
- Pmatrix temp;
- Ppoint winmin, winmax, vpmin, vpmax, wincentre, vpcentre;
- Pfloat minscale;
-
- *error = ptkcpcok; /* assume OK */
- if (!validbounds(box1))
- {
- *error = -1;
- return;
- }
- winmin = ptk_point(box1->x_min, box1->y_min);
- winmax = ptk_point(box1->x_max, box1->y_max);
- vpmin = ptk_point(box2->x_min, box2->y_min);
- vpmax = ptk_point(box2->x_max, box2->y_max);
-
- winscale = ptk_subv(&winmax, &winmin);
- wincentre = ptk_scalev(&winscale, 0.5);
- wincentre = ptk_addv(&winmin, &wincentre);
- wincentre = ptk_scalev(&wincentre, -1.0);
- vpscale = ptk_subv(&vpmax, &vpmin);
- vpcentre = ptk_scalev(&vpscale, 0.5);
- vpcentre = ptk_addv(&vpmin, &vpcentre);
- if (winscale.x == 0.0)
- winscale.x = 1.0;
- else
- winscale.x = vpscale.x / winscale.x;
- if (winscale.y == 0.0)
- winscale.y = 1.0;
- else
- winscale.y = vpscale.y / winscale.y;
- if (preserve)
- {
- minscale = PTKMIN(winscale.x, winscale.y);
- winscale = ptk_point(minscale, minscale);
- }
- ptk_shift(&vpcentre, PTYPE_REPLACE, temp);
- ptk_scale(&winscale, PTYPE_PRECONCAT, temp);
- ptk_shift(&wincentre, PTYPE_PRECONCAT, temp);
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_boxtobox */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_accumulatetran3(C(Ppoint3 *) fixed, C(Ppoint3 *) shift,
- C(Pfloat) rotx, C(Pfloat) roty,
- C(Pfloat) rotz, C(Ppoint3 *) scale,
- C(Pcompose_type) operation,
- C(Pmatrix3) matrix)
- PreANSI(Ppoint3 *fixed)
- PreANSI(Ppoint3 *shift)
- PreANSI(Pfloat rotx)
- PreANSI(Pfloat roty)
- PreANSI(Pfloat rotz)
- PreANSI(Ppoint3 *scale)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{fixed}{origin}{IN}
- ** \param{Ppoint3 *}{shift}{shift factor}{IN}
- ** \param{Pfloat}{rotx}{x rotation}{IN}
- ** \param{Pfloat}{rotx}{y rotation}{IN}
- ** \param{Pfloat}{rotx}{z rotation}{IN}
- ** \param{Ppoint3 *}{scale}{scale factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes the specified 3D
- ** shift, scale and rotate transformations, in the order
- ** scale, rotate, shift,
- ** and then concatenates the resulting transformation
- ** with the specified matrix on the basis of \pardesc{operation}.}
- */
- {
- Pmatrix3 temp;
- Ppoint3 mfixed;
-
- mfixed = ptk_scalev3(fixed, -1.0);
- ptk_shift3(shift, PTYPE_REPLACE, temp);
- ptk_shift3(fixed, PTYPE_PRECONCAT, temp);
- ptk_rotate3(rotx, PTKEXAXIS, PTYPE_PRECONCAT, temp);
- ptk_rotate3(roty, PTKEYAXIS, PTYPE_PRECONCAT, temp);
- ptk_rotate3(rotz, PTKEZAXIS, PTYPE_PRECONCAT, temp);
- ptk_scale3(scale, PTYPE_PRECONCAT, temp);
- ptk_shift3(&mfixed, PTYPE_PRECONCAT, temp);
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_accumulatetran3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_accumulatetran(C(Ppoint *) fixed, C(Ppoint *) shift,
- C(Pfloat) rot, C(Ppoint *) scale,
- C(Pcompose_type) operation,
- C(Pmatrix) matrix)
- PreANSI(Ppoint *fixed)
- PreANSI(Ppoint *shift)
- PreANSI(Pfloat rot)
- PreANSI(Ppoint *scale)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Ppoint *}{fixed}{origin}{IN}
- ** \param{Ppoint *}{shift}{shift factor}{IN}
- ** \param{Pfloat}{rotx}{x rotation}{IN}
- ** \param{Ppoint *}{scale}{scale factor}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes the specified 2D
- ** shift, scale and rotate transformations, in the order
- ** scale, rotate, shift,
- ** and then concatenates the resulting transformation
- ** with the specified matrix on the basis of \pardesc{operation}.}
- */
- {
- Pmatrix temp;
- Ppoint mfixed;
-
- mfixed = ptk_scalev(fixed, -1.0);
- ptk_shift(shift, PTYPE_REPLACE, temp);
- ptk_shift(fixed, PTYPE_PRECONCAT, temp);
- ptk_rotate(rot, PTKEXAXIS, PTYPE_PRECONCAT, temp);
- ptk_scale(scale, PTYPE_PRECONCAT, temp);
- ptk_shift(&mfixed, PTYPE_PRECONCAT, temp);
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_accumulatetran */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_evalvieworientation3(C(Ppoint3 *) viewrefpoint,
- C(Ppoint3 *) viewplanenormal,
- C(Ppoint3 *) viewupvector,
- C(Pcompose_type) operation,
- C(Pmatrix3) matrix, C(Pint *)error)
- PreANSI(Ppoint3 *viewrefpoint)
- PreANSI(Ppoint3 *viewplanenormal)
- PreANSI(Ppoint3 *viewupvector)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{viewrefpoint}{view reference point}{IN}
- ** \param{Ppoint3 *}{viewplanenormal}{view plane normal}{IN}
- ** \param{Ppoint3 *}{viewupvector}{view up vector}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a 3D PHIGS view orientation matrix on the basis of
- ** a specified view reference point (\pardesc{viewrefpoint}), a
- ** view plane normal (\pardesc{viewplanenormal}) and a view up vector
- ** (\pardesc{viewupvector}). If the function succeeds,
- ** \pardesc{error} is set to
- ** \pardesc{ptkcpcok}. Otherwise,
- ** \pardesc{error} is 61 if the view plane normal is null,
- ** 63 if the view up vector is null,
- ** and 58 if the cross product of the view up vector
- ** and the view plane normal is null.}
- */
- {
- Ppoint3 uaxis, vaxis, naxis, vuvxvpn;
- Pmatrix3 temp;
-
- *error = ptkcpcok;
- if (ptk_nullv3(viewplanenormal))
- {
- *error = 61;
- }
- else
- if (ptk_nullv3(viewupvector))
- {
- *error = 63;
- }
- else
- {
- vuvxvpn = ptk_crossv3(viewupvector, viewplanenormal);
- if (ptk_nullv3(&vuvxvpn))
- *error = 58;
- else
- *error = ptkcpcok;
- }
- if (*error != ptkcpcok)
- {
- return;
- } /* if error = 0 */
- /* generate from viewplanenormal and viewupvector a set
- ** of orthogonal axes denoted by uaxis, vaxis, naxis
- */
- naxis = ptk_unitv3(viewplanenormal);
- uaxis = ptk_unitv3(&vuvxvpn);
- vaxis = ptk_crossv3(&naxis, &uaxis);
- vaxis = ptk_unitv3(&vaxis);
- /* form view orientation matrix */
- ptk_unitmatrix3(temp);
- temp[0][0] = uaxis.x;
- temp[0][1] = uaxis.y;
- temp[0][2] = uaxis.z;
- temp[0][3] = -(uaxis.x * viewrefpoint->x + uaxis.y *
- viewrefpoint->y + uaxis.z * viewrefpoint->z);
- temp[1][0] = vaxis.x;
- temp[1][1] = vaxis.y;
- temp[1][2] = vaxis.z;
- temp[1][3] = -(vaxis.x * viewrefpoint->x + vaxis.y *
- viewrefpoint->y + vaxis.z * viewrefpoint->z);
- temp[2][0] = naxis.x;
- temp[2][1] = naxis.y;
- temp[2][2] = naxis.z;
- temp[2][3] = -(naxis.x * viewrefpoint->x + naxis.y *
- viewrefpoint->y + naxis.z * viewrefpoint->z);
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_evalvieworientation3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_evalvieworientation(C(Ppoint *) viewrefpoint,
- C(Ppoint *) viewupvector,
- C(Pcompose_type) operation,
- C(Pmatrix) matrix, C(Pint *)error)
- PreANSI(Ppoint *viewrefpoint)
- PreANSI(Ppoint *viewupvector)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Ppoint *}{viewrefpoint}{view reference point}{IN}
- ** \param{Ppoint *}{viewupvector}{view up vector}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes
- ** a 2D PHIGS view orientation matrix on the basis of
- ** a specified view reference point (\pardesc{viewrefpoint})
- ** and a view up vector
- ** (\pardesc{viewupvector}). If the function succeeds,
- ** \pardesc{error} is set to \pardesc{ptkcpcok}. Otherwise,
- ** \pardesc{error} is 63 if the view up vector is null.}
- */
- {
- Ppoint3 uaxis, vaxis, naxis, vuvxvpn;
- Pmatrix temp;
-
- *error = ptkcpcok;
- if (ptk_nullv(viewupvector))
- {
- *error = 63;
- }
- if (*error != ptkcpcok)
- {
- return;
- } /* if error = 0 */
- /* generate from viewplanenormal and viewupvector a set
- ** of orthogonal axes denoted by uaxis, vaxis, naxis
- */
- naxis = ptk_point3(0.0, 0.0, 1.0);
- vaxis = ptk_point3(viewupvector->x, viewupvector->y, 0.0);
- vaxis = ptk_unitv3(&vaxis);
- /* uaxis = ptk_crossv3(naxis, vaxis); */
- uaxis = ptk_unitv3(&uaxis);
- /* form view orientation matrix */
- ptk_unitmatrix(temp);
- temp[0][0] = uaxis.x;
- temp[0][1] = uaxis.y;
- temp[0][2] = uaxis.z;
- /* temp[0][3] = -(uaxis.x * viewrefpoint->x + uaxis.y * viewrefpoint->y); */
- temp[1][0] = vaxis.x;
- temp[1][1] = vaxis.y;
- temp[1][2] = 0.0;
- /* temp[1][3] = -(vaxis.x * viewrefpoint->x + vaxis.y * viewrefpoint->y); */
- temp[2][0] = naxis.x;
- temp[2][1] = naxis.y;
- temp[2][2] = naxis.z;
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_evalvieworientation */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_evalviewmapping3(C(Plimit3 *) wlimits, C(Plimit3 *) vlimits,
- C(Pproj_type) viewtype,
- C(Ppoint3 *) refpoint, C(Pfloat) vplanedist,
- C(Pcompose_type) operation, C(Pmatrix3) matrix,
- C(Pint *)error)
- PreANSI(Plimit3 *wlimits)
- PreANSI(Plimit3 *vlimits)
- PreANSI(Pproj_type viewtype)
- PreANSI(Ppoint3 *refpoint)
- PreANSI(Pfloat vplanedist)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Plimit3 *}{wlimits}{window limits}{IN}
- ** \param{Plimit3 *}{vlimits}{viewport limits}{IN}
- ** \param{Pproj\_type}{viewtype}{projection type}{IN}
- ** \param{Ppoint3 *}{refpoint}{projection reference point}{IN}
- ** \param{Pfloat}{vplanedist}{view plane distance}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function evaluates a 3D PHIGS view mapping matrix.
- ** If the function succeeds,
- ** \pardesc{error} is set to \pardesc{ptkcpcok}. Otherwise,
- ** \pardesc{error} is
- ** 329 if the window limits are not valid,
- ** 336 if the back plane is in front of front plane,
- ** 330 if the viewport limits are not valid,
- ** 335 if the projection reference point is on the view plane,
- ** and 340 if the projection reference point is between front and back planes.}
- */
- {
- Ppoint3 projectordirn, viewwindowcentre, vref;
- Pmatrix3 temp;
- Plimit3 templim;
- Pint err;
-
- templim = *wlimits;
- *error = ptkcpcok;
- /* check for valid window limits */
- if (templim.x_min >= templim.x_max ||
- templim.y_min >= templim.y_max)
- {
- *error = 329;
- return;
- }
- /* check that back plane is not in front of front plane */
- if (templim.z_min >= templim.z_max)
- {
- *error = 336;
- return;
- }
- /* check for valid viewport limits */
- if (!validbounds3(vlimits))
- {
- *error = 330;
- return;
- }
- /* check that PRP not positioned on the view plane */
- if (ptk_equal(refpoint->z, vplanedist))
- {
- *error = 335;
- return;
- }
- /* check that PRP not between the front and back planes */
- if (refpoint->z < templim.z_max && refpoint->z > templim.z_min)
- {
- *error = 340;
- return;
- }
- /* if everything is OK error is set to zero and a value computed for
- ** matrix.
- */
- *error = ptkcpcok;
- ptk_unitmatrix3(temp);
- switch (viewtype)
- {
- case PTYPE_PERSPECT:
- temp[0][0] = refpoint->z - vplanedist;
- temp[0][2] = -refpoint->x;
- temp[0][3] = refpoint->x * vplanedist;
- temp[1][0] = 0.0;
- temp[1][1] = refpoint->z - vplanedist;
- temp[1][2] = -refpoint->y;
- temp[1][3] = refpoint->y * vplanedist;
- temp[2][2] = 0.0;
- temp[2][3] = 1.0;
- temp[3][2] = -1.0;
- temp[3][3] = refpoint->z;
- break;
-
- case PTYPE_PARAL:
- viewwindowcentre.x = (templim.x_min + templim.x_max) / 2;
- viewwindowcentre.y = (templim.y_min + templim.y_max) / 2;
- viewwindowcentre.z = vplanedist;
- projectordirn = ptk_subv3(refpoint, &viewwindowcentre);
- projectordirn = ptk_scalev3(&projectordirn,
- 1.0 / (refpoint->z - vplanedist));
- temp[0][2] = -projectordirn.x;
- temp[0][3] = vplanedist * projectordirn.x;
- temp[1][2] = -projectordirn.y;
- temp[1][3] = vplanedist * projectordirn.y;
- break;
- }
- /* The z coordinate is unchanged by the transformation matrix above for
- ** parallel projection types and changed for perspective projection
- ** types. Different action is therefore required in each case so that
- ** points at the front and back planes are always mapped onto points at
- ** the front and back of the projection viewport
- */
- if (viewtype == PTYPE_PERSPECT)
- {
- templim.z_min = 1.0 / (refpoint->z - templim.z_min);
- templim.z_max = 1.0 / (refpoint->z - templim.z_max);
- }
- ptk_box3tobox3(&templim, vlimits, FALSE, PTYPE_POSTCONCAT, temp, &err);
- ptk_concatenatematrix3(operation, temp, matrix, matrix);
- } /* ptk_evalviewmapping3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_evalviewmapping(C(Plimit *) wlimits, C(Plimit *) vlimits,
- C(Pcompose_type) operation, C(Pmatrix) matrix,
- C(Pint *)error)
- PreANSI(Plimit *wlimits)
- PreANSI(Plimit *vlimits)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Plimit *}{wlimits}{window limits}{IN}
- ** \param{Plimit *}{vlimits}{viewport limits}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function evaluates a 2d PHIGS view mapping matrix.
- ** If the function succeeds,
- ** \pardesc{error} is set to \pardesc{ptkcpcok}. Otherwise,
- ** \pardesc{error} is
- ** 329 if the window limits are not valid,
- ** and 330 if the viewport limits are not valid.}
- */
- {
- Pmatrix temp;
- Pint err;
-
- *error = ptkcpcok;
- /* check for valid window limits */
- if (wlimits->x_min >= wlimits->x_max ||
- wlimits->y_min >= wlimits->y_max)
- {
- *error = 329;
- return;
- }
- /* check for valid viewport limits */
- if (!validbounds(vlimits))
- {
- *error = 330;
- return;
- }
- /* if everything is OK error is set to zero and a value computed for
- ** matrix.
- */
- *error = ptkcpcok;
- ptk_unitmatrix(temp);
- ptk_boxtobox(wlimits, vlimits, FALSE, PTYPE_POSTCONCAT, temp, &err);
- ptk_concatenatematrix(operation, temp, matrix, matrix);
- } /* ptk_evalviewmapping */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_stackmatrix3(C(Pmatrix3) matrix)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{IN}
- ** \paramend
- ** \blurb{This function pushes
- ** the $4 \times 4$ matrix \pardesc{matrix} onto the transformation stack.}
- */
- {
- newone3 = (ptksstack3 *)malloc(sizeof(ptksstack3));
- newone3->ptkpnext = listhead3;
- memcpy(newone3->ptkamat, matrix, sizeof(Pmatrix3));
- listhead3 = newone3;
- } /* ptk_stackmatrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_stackmatrix(C(Pmatrix) matrix)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix}{matrix}{3x3 matrix}{IN}
- ** \paramend
- ** \blurb{This function pushes the $3 \times 3$ matrix \pardesc{matrix}
- ** onto the transformation stack.}
- */
- {
- newone = (ptksstack *)malloc(sizeof(ptksstack));
- newone->ptkpnext = listhead;
- memcpy(newone->ptkamat, matrix, sizeof(Pmatrix));
- listhead = newone;
- } /* ptk_stackmatrix */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_unstackmatrix3(C(Pmatrix3) matrix)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function
- ** pops a $4 \times 4$ matrix
- ** from the transformation stack and returns it in
- ** \pardesc{matrix}.}
- */
- {
- if (listhead3 == NULL)
- return;
- memcpy(matrix, listhead3->ptkamat, sizeof(Pmatrix3));
- newone3 = listhead3->ptkpnext;
- free(listhead3);
- listhead3 = newone3;
- } /* ptk_unstackmatrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_unstackmatrix(C(Pmatrix) matrix)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix}{matrix}{3x3 matrix}{OUT}
- ** \paramend
- ** \blurb{This function pops a $3 \times 3$ matrix
- ** from the transformation stack and returns it in
- ** \pardesc{matrix}.}
- */
- {
- if (listhead == NULL)
- return;
- memcpy(matrix, listhead->ptkamat, sizeof(Pmatrix));
- newone = listhead->ptkpnext;
- free(listhead);
- listhead = newone;
- } /* ptk_unstackmatrix */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_examinestackmatrix3(C(Pmatrix3) matrix)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{IN}
- ** \paramend
- ** \blurb{This function returns the top entry on the transformation stack.
- ** The stack is not disturbed.}
- */
- {
- if (listhead3 != NULL)
- memcpy(matrix, listhead3->ptkamat, sizeof(Pmatrix3));
- } /* ptk_examinestackmatrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_examinestackmatrix(C(Pmatrix) matrix)
- PreANSI(Pmatrix matrix)
- /*
- ** \parambegin
- ** \param{Pmatrix}{matrix}{3x3 matrix}{IN}
- ** \paramend
- ** \blurb{This function returns the top entry on the transformation stack.
- ** The stack is not disturbed.}
- */
- {
- if (listhead != NULL)
- memcpy(matrix, listhead->ptkamat, sizeof(Pmatrix));
- } /* ptk_examinestackmatrix */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_3ptto3pt(C(Ppoint3 *) p1, C(Ppoint3 *) p2, C(Ppoint3 *) p3,
- C(Ppoint3 *) q1, C(Ppoint3 *) q2, C(Ppoint3 *) q3,
- C(Pcompose_type) operation, C(Pmatrix3) matrix,
- C(Pint *)error)
- PreANSI(Ppoint3 *p1)
- PreANSI(Ppoint3 *p2)
- PreANSI(Ppoint3 *p3)
- PreANSI(Ppoint3 *q1)
- PreANSI(Ppoint3 *q2)
- PreANSI(Ppoint3 *q3)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{p1}{3D point}{IN}
- ** \param{Ppoint3 *}{p2}{3D point}{IN}
- ** \param{Ppoint3 *}{p3}{3D point}{IN}
- ** \param{Ppoint3 *}{q1}{3D point}{IN}
- ** \param{Ppoint3 *}{q2}{3D point}{IN}
- ** \param{Ppoint3 *}{q3}{3D point}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function returns the 3 point to 3 point transformation as
- ** described in \cite{mort:geom}, pages 353--355.
- ** The transformation has the following properties:
- ** \pardesc{p1} is transformed onto \pardesc{q1};
- ** the vector \pardesc{(p2-p1)} is transformed to be parallel to the vector
- ** \pardesc{(q2-q1)};
- ** the plane containing the three points \pardesc{p1, p2, p3} is
- ** transformed into the plane containing \pardesc{q1, q2, q3}.
- ** The transformation is concatenated with the $4 \times 4$ matrix
- ** \pardesc{matrix} on the basis of \pardesc{operation}.
- ** If the parameters are invalid, \pardesc{error} is set to
- ** -1. Otherwise, its value is \pardesc{ptkcpcok}.}
- */
- {
- Pmatrix3 tempmat, invvmatrix, wmatrix;
- Ppoint3 v1, v2, v3, w1, w2, w3, temp;
-
- /* form 2 right-hand orthogonal systems from the given points */
- *error = ptkcpcok;
- v1 = ptk_subv3(p2, p1);
- v1 = ptk_unitv3(&v1);
- v3 = ptk_subv3(p3, p1);
- v3 = ptk_crossv3(&v1, &v3);
- v3 = ptk_unitv3(&v3);
- v2 = ptk_crossv3(&v3, &v1);
- v2 = ptk_unitv3(&v2);
- temp = ptk_subv3(q2, q1);
- w1 = ptk_unitv3(&temp);
- temp = ptk_subv3(q3, q1);
- temp = ptk_crossv3(&w1, &temp);
- w3 = ptk_unitv3(&temp);
- temp = ptk_crossv3(&w3, &w1);
- w2 = ptk_unitv3(&temp);
-
- /* if any of v1..v3, w1..w3 are null vectors then the parameters are
- ** invalid.
- */
- if (ptk_nullv3(&v1) || ptk_nullv3(&v2) || ptk_nullv3(&v3) ||
- ptk_nullv3(&w1) || ptk_nullv3(&w2) || ptk_nullv3(&w3))
- {
- *error = -1;
- return;
- }
- *error = ptkcpcok;
- ptk_unitmatrix3(invvmatrix);
- invvmatrix[0][0] = v1.x;
- invvmatrix[0][1] = v1.y;
- invvmatrix[0][2] = v1.z;
- invvmatrix[1][0] = v2.x;
- invvmatrix[1][1] = v2.y;
- invvmatrix[1][2] = v2.z;
- invvmatrix[2][0] = v3.x;
- invvmatrix[2][1] = v3.y;
- invvmatrix[2][2] = v3.z;
- ptk_unitmatrix3(wmatrix);
- wmatrix[0][0] = w1.x;
- wmatrix[1][0] = w1.y;
- wmatrix[2][0] = w1.z;
- wmatrix[0][1] = w2.x;
- wmatrix[1][1] = w2.y;
- wmatrix[2][1] = w2.z;
- wmatrix[0][2] = w3.x;
- wmatrix[1][2] = w3.y;
- wmatrix[2][2] = w3.z;
-
- /* shift points at origin onto q1 */
-
- ptk_shift3(q1, PTYPE_REPLACE, tempmat);
- ptk_concatenatematrix3(PTYPE_PRECONCAT, wmatrix, wmatrix, tempmat);
- ptk_concatenatematrix3(PTYPE_PRECONCAT, invvmatrix, tempmat, tempmat);
-
- /* shift p1 to origin */
- temp = ptk_scalev3(p1, -1.0);
- ptk_shift3(&temp, PTYPE_PRECONCAT, tempmat);
- ptk_concatenatematrix3(operation, tempmat, matrix, matrix);
- } /* ptk_3ptto3pt */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_0to3pt(C(Ppoint3 *) origin, C(Ppoint3 *) xdirn,
- C(Ppoint3 *) ydirn, C(Pcompose_type) operation, C(Pmatrix3) matrix)
- PreANSI(Ppoint3 *origin)
- PreANSI(Ppoint3 *xdirn)
- PreANSI(Ppoint3 *ydirn)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{origin}{origin of axes}{IN}
- ** \param{Ppoint3 *}{xdirn}{x direction}{IN}
- ** \param{Ppoint3 *}{y dirn}{y direction}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function computes an object transformation which
- ** maps unit vectors
- ** along the $x$, $y$ and $z$ axes onto unit vectors along the
- ** corresponding axes
- ** of the new coordinate system.}
- */
- {
- Ppoint3 xaxis, yaxis, zaxis;
- Pmatrix3 objectxform;
-
- /* A new coordinate system is defined, centred at origin, its x-axis
- ** parallel to xdirn and the y-axis parallel to the component of ydirn
- ** which is perpendicular to the x-axis. The transformation matrix returned
- ** is an object transformation.
- */
-
- /* work out unit vectors along the axes of new coordinate system */
-
- xaxis = ptk_unitv3(xdirn);
- zaxis = ptk_crossv3(&xaxis, ydirn);
- zaxis = ptk_unitv3(&zaxis);
- yaxis = ptk_crossv3(&zaxis, &xaxis);
- yaxis = ptk_unitv3(&yaxis);
-
- /* form matrices - see "An Implementation of the GKS-3D/PHIGS Viewing
- ** Pipeline" for the maths.
- */
-
- ptk_unitmatrix3(objectxform);
- objectxform[0][0] = xaxis.x;
- objectxform[1][0] = xaxis.y;
- objectxform[2][0] = xaxis.z;
- objectxform[0][1] = yaxis.x;
- objectxform[1][1] = yaxis.y;
- objectxform[2][1] = yaxis.z;
- objectxform[0][2] = zaxis.x;
- objectxform[1][2] = zaxis.y;
- objectxform[2][2] = zaxis.z;
- objectxform[0][3] = origin->x;
- objectxform[1][3] = origin->y;
- objectxform[2][3] = origin->z;
- ptk_concatenatematrix3(operation, objectxform, matrix, matrix);
-
- /* To output text, call above procedure to get the character plane
- ** transformation:
- **
- ** ptk_0to3pt( text_point, text_direction_vector_1,
- ** text_direction_vector_2, PVReplacematrix,char_plane_xform)
- **
- ** As each point of the text is output, transform it by:
- **
- ** output_pipeline . char_plane_xform
- */
- } /* ptk_0to3pt */
-
- /*---------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_oto3pt(C(Ppoint3 *) origin, C(Ppoint3 *) xdirn,
- C(Ppoint3 *) ydirn, C(Pcompose_type) operation, C(Pmatrix3) matrix)
- PreANSI(Ppoint3 *origin)
- PreANSI(Ppoint3 *xdirn)
- PreANSI(Ppoint3 *ydirn)
- PreANSI(Pcompose_type operation)
- PreANSI(Pmatrix3 matrix)
- /*
- ** \parambegin
- ** \param{Ppoint3 *}{origin}{origin of axes}{IN}
- ** \param{Ppoint3 *}{xdirn}{x direction}{IN}
- ** \param{Ppoint3 *}{y dirn}{y direction}{IN}
- ** \param{Pcompose\_type}{operation}{concatenation operation}{IN}
- ** \param{Pmatrix3}{matrix}{4x4 matrix}{OUT}
- ** \paramend
- ** \blurb{This function performs the same operation as
- ** \pardesc{ptk\_0to3pt}, except the name has an \pardesc{o}\
- ** (oh) instead of \pardesc{0}\ (zero). This function is provided for members
- ** of the Fumbly Fingers Club.}
- */
- {
- ptk_0to3pt(origin, xdirn, ydirn, operation, matrix);
- } /* ptk_oto3pt */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_invertmatrix3(C(Pmatrix3) a, C(Pmatrix3) ainverse,
- C(Pint *)error)
- PreANSI(Pmatrix3 a)
- PreANSI(Pmatrix3 ainverse)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Pmatrix3}{a}{4x4 matrix}{IN}
- ** \param{Pmatrix3}{ainverse}{4x4 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes the inverse of the $4 \times 4$
- ** matrix \pardesc{a},
- ** returning the result in \pardesc{ainverse}.
- ** If matrix \pardesc{a} is singular, then
- ** \pardesc{error} is set to $-1$, and \pardesc{ainverse} is undefined,
- ** otherwise \pardesc{error} is set to \pardesc{ptkcpcok}.
- ** This function uses Crout's method, a modification of Gaussian
- ** elimination.}
- */
- {
- Pfloat b[4], c[4];
- Pfloat w, y;
- Pint z[4];
- Pint i, j, k, l, p;
-
- *error = -1;
- memcpy(ainverse, a, sizeof(Pmatrix3));
- for (j = 1; j <= 4; j++)
- z[j - 1] = j;
- for (i = 1; i <= 4; i++)
- {
- k = i;
- y = ainverse[i - 1][i - 1];
- l = i - 1;
- p = i + 1;
- for (j = p; j <= 4; j++)
- {
- w = ainverse[i - 1][j - 1];
- if (fabs(w) > fabs(y))
- {
- k = j;
- y = w;
- }
- }
- if (ptk_equal(y, 0.0)) /* matrix has no inverse */
- return;
- y = 1.0 / y;
- for (j = 0; j <= 3; j++)
- {
- c[j] = ainverse[j][k - 1];
- ainverse[j][k - 1] = ainverse[j][i - 1];
- ainverse[j][i - 1] = -c[j] * y;
- ainverse[i - 1][j] *= y;
- b[j] = ainverse[i - 1][j];
- }
- ainverse[i - 1][i - 1] = y;
- j = z[i - 1];
- z[i - 1] = z[k - 1];
- z[k - 1] = j;
- for (k = 0; k < l; k++)
- {
- for (j = 0; j < l; j++)
- ainverse[k][j] -= b[j] * c[k];
- for (j = p - 1; j <= 3; j++)
- ainverse[k][j] -= b[j] * c[k];
- }
- for (k = p - 1; k <= 3; k++)
- {
- for (j = 0; j < l; j++)
- ainverse[k][j] -= b[j] * c[k];
- for (j = p - 1; j <= 3; j++)
- ainverse[k][j] -= b[j] * c[k];
- }
- }
- for (i = 0; i <= 3; i++)
- {
- do
- {
- k = z[i];
- if (k != i + 1)
- {
- for (j = 0; j <= 3; j++)
- {
- w = ainverse[i][j];
- ainverse[i][j] = ainverse[k - 1][j];
- ainverse[k - 1][j] = w;
- }
- p = z[i];
- z[i] = z[k - 1];
- z[k - 1] = p;
- }
- } while (k != i + 1);
- }
- *error = ptkcpcok;
- } /* ptk_invertmatrix3 */
-
- /*--------------------------------------------------------------------------*/
-
- /*function:external*/
- extern void ptk_invertmatrix(C(Pmatrix) a, C(Pmatrix) ainverse,
- C(Pint *) error)
- PreANSI(Pmatrix a)
- PreANSI(Pmatrix ainverse)
- PreANSI(Pint *error)
- /*
- ** \parambegin
- ** \param{Pmatrix}{a}{3x3 matrix}{IN}
- ** \param{Pmatrix}{ainverse}{3x3 matrix}{OUT}
- ** \param{Pint *}{error}{error code}{OUT}
- ** \paramend
- ** \blurb{This function computes the inverse of the $3 \times 3$
- ** matrix \pardesc{a},
- ** returning the result in \pardesc{ainverse}.
- ** If matrix \pardesc{a} is singular, then
- ** \pardesc{error} is set to $-1$, and \pardesc{ainverse} is undefined,
- ** otherwise \pardesc{error} is set to \pardesc{ptkcpcok}.
- ** This function uses Crout's method, a modification of Gaussian
- ** elimination.}
- */
- {
- Pfloat b[3], c[3];
- Pfloat w, y;
- Pint z[3];
- Pint i, j, k, l, p;
-
- *error = -1;
- memcpy(ainverse, a, sizeof(Pmatrix));
- for (j = 1; j <= 3; j++)
- z[j - 1] = j;
- for (i = 1; i <= 3; i++)
- {
- k = i;
- y = ainverse[i - 1][i - 1];
- l = i - 1;
- p = i + 1;
- for (j = p; j <= 3; j++)
- {
- w = ainverse[i - 1][j - 1];
- if (fabs(w) > fabs(y))
- {
- k = j;
- y = w;
- }
- }
- if (ptk_equal(y, 0.0)) /* matrix has no inverse */
- return;
- y = 1.0 / y;
- for (j = 0; j <= 2; j++)
- {
- c[j] = ainverse[j][k - 1];
- ainverse[j][k - 1] = ainverse[j][i - 1];
- ainverse[j][i - 1] = -c[j] * y;
- ainverse[i - 1][j] *= y;
- b[j] = ainverse[i - 1][j];
- }
- ainverse[i - 1][i - 1] = y;
- j = z[i - 1];
- z[i - 1] = z[k - 1];
- z[k - 1] = j;
- for (k = 0; k < l; k++)
- {
- for (j = 0; j < l; j++)
- ainverse[k][j] -= b[j] * c[k];
- for (j = p - 1; j <= 2; j++)
- ainverse[k][j] -= b[j] * c[k];
- }
- for (k = p - 1; k <= 2; k++)
- {
- for (j = 0; j < l; j++)
- ainverse[k][j] -= b[j] * c[k];
- for (j = p - 1; j <= 2; j++)
- ainverse[k][j] -= b[j] * c[k];
- }
- }
- for (i = 0; i <= 2; i++)
- {
- do
- {
- k = z[i];
- if (k != i + 1)
- {
- for (j = 0; j <= 2; j++)
- {
- w = ainverse[i][j];
- ainverse[i][j] = ainverse[k - 1][j];
- ainverse[k - 1][j] = w;
- }
- p = z[i];
- z[i] = z[k - 1];
- z[k - 1] = p;
- }
- } while (k != i + 1);
- }
- *error = ptkcpcok;
- } /* ptk_invertmatrix */
-
- /*--------------------------------------------------------------------------*/
-
- /* end of tran.c */
-